

#include "Zone.h"

#include <stdio.h>
#include <assert.h>

void zonInit (Zone* p_zone, int num_zone)
{
    int i,j;
    int reslecture;
    FILE* fichier = NULL;
    char chemin_fichier_zone[10];
    char car_temp;
	int num;

	/* Initialisation chemin de la zone à charger : se trouve dans le répertoire maps et le fichier a pour nom son numéro de zone qui doit donc être converti en chaîne de caractères */
    sprintf(chemin_fichier_zone, "maps/%d", num_zone);

	/* Ouverture du fichier a lire*/
    fichier = fopen(chemin_fichier_zone, "r");
    if (fichier==NULL)
	{
		printf("Impossible d'ouvrir le fichier");
		exit(EXIT_FAILURE);
	}

	/* Lecture de la premiere ligne */
    reslecture = fscanf (fichier, "Zelda - zone %d :\n", &num);
    assert (reslecture == 1 && num==num_zone); /* petite vérification */

	/* Lecture de la dimension d'un coté de la zone (les zones sont carrées) */
    reslecture = fscanf (fichier, "Dimension : %d\n", &(p_zone->dimension));
    assert (reslecture == 1);

	/* Lecture des numéros des zones vers lesquelles il existe un passage */ /* Les num_zone peuvent conternir -1 s'il n'y a pas de passage vers le nord/sud/... ...peut-être ne pas mettre tout simplement ??? */
    reslecture = fscanf (fichier, "Nord : %d\n",&p_zone->num_zone_nord);
    assert (reslecture == 1);
	reslecture = fscanf (fichier, "Sud : %d\n",&p_zone->num_zone_sud);
    assert (reslecture == 1);
    reslecture = fscanf (fichier, "Est : %d\n",&p_zone->num_zone_est);
    assert (reslecture == 1);
    reslecture = fscanf (fichier, "Ouest : %d\n",&p_zone->num_zone_ouest);
    assert (reslecture == 1);

    /*Allocation d'un tableau 2D de BlocObjets de taille DIM*DIM i.e. un tableau de DIM tableaux 1D de BlocObjets */
    p_zone->tab = (BlocObjet**) malloc(sizeof(BlocObjet*) * p_zone->dimension);
    for (i=0 ; i<p_zone->dimension ; i++)
    {
        p_zone->tab[i] = (BlocObjet*) malloc(sizeof(BlocObjet) * p_zone->dimension);
    }

	/* Remplissage de ce tableau de Blocs */
    for (i=0 ; i<p_zone->dimension ; i++)
    {
        for (j=0 ; j<(p_zone->dimension) ; j++)
        {
            reslecture = fscanf(fichier,"%c", &car_temp);
            assert(reslecture==1);

            bloSetDepuisCaractere(&p_zone->tab[i][j], car_temp);
        }

        /* Comme on utilise des caractères pour stocker les blocs, on a p_zone->dimension caractères par ligne qui correspondes à des blocs + 1 pour le retour à la ligne */
        /* On jette donc ce dernier caractère dans lacar_temp*/
        j++;
        reslecture = fscanf(fichier,"%c", &car_temp);
        assert(reslecture==1 && car_temp=='\n');
    }

	reslecture = fscanf (fichier, "Nombre de monstres placés aléatoirement : %d\n",&p_zone->nb_monstres_aleatoires);
    assert (reslecture == 1);
	/* A FAIRE : ajouter des monstres à placement manuel précis et fixe (exemple : gardes) */

    fclose(fichier);
}

void zonLibere (Zone* p_zone)
{
    int i;

    for (i=0 ; i<p_zone->dimension ; i++)
    {
        free (p_zone->tab[i]);
    }
    free(p_zone->tab);
}

Zone* zonCree (int num_zone)
{
	Zone* p_zone = (Zone*) malloc(sizeof(Zone));

	zonInit(p_zone, num_zone);

	return p_zone;
}

void zonDetruit (Zone* p_zone)
{
	zonLibere(p_zone);
	free(p_zone);
	p_zone = NULL;
}



int zonGetNbMonstresAleatoires(const Zone* p_zone)
{
	return p_zone->nb_monstres_aleatoires;
}



BlocObjet* zonGetPBlocObjetXY(const Zone* p_zone, int x, int y)
{
    assert( 0<=x && x<p_zone->dimension && 0<=y && y<p_zone->dimension);

    return &p_zone->tab[y][x];
}

Bloc zonGetBlocXY (const Zone* p_zone, int x, int y)
{
    assert( 0<=x && x<p_zone->dimension && 0<=y && y<p_zone->dimension);

    return bloGetBloc( zonGetPBlocObjetXY(p_zone, x, y) );
}

Objet zonGetObjetXY(const Zone* p_zone, int x, int y)
{
    assert( 0<=x && x<p_zone->dimension && 0<=y && y<p_zone->dimension);

    return bloGetObjet( zonGetPBlocObjetXY(p_zone, x, y) );
}



bool zonEstPositionAccessible (const Zone* p_zone, int x, int y)
{
    if (x<0 || x >= p_zone->dimension || y<0 || y >= p_zone->dimension) /* On ne peut pas sortir de la zone => inaccessible */
    {
    	return false;
    }
	else 	/* on récupère le résultat de la fonction qui dit si un type de bloc est accessible ou non en lui passant le bloc en question */
	{
		return bloAccessible(zonGetPBlocObjetXY(p_zone, x, y));
	}
}

/* Note : on interdit les changeurs de zone dans les coins, ils seraient ambigus sur la zone vers laquelle ils pointent */
bool zonEstChangeurZone (const Zone* p_zone, int x, int y)
{
    assert( 0<=x && x<p_zone->dimension && 0<=y && y<p_zone->dimension);
    if ( (x==0 && y==0) ||
		 (x==p_zone->dimension-1 && y==0) ||
		 (x==p_zone->dimension-1 && y==p_zone->dimension-1) ||
		 (x==0 && y==p_zone->dimension-1)
		)
	{
		fprintf(stderr, "Attention, la zone a mal été dessinée, un changeur de zone en (%d,%d) est ambigu, il ne se comportera pas forcément comme souhaité. \n", x ,y);
	}

	return bloChangeurDeZone(zonGetBlocXY(p_zone, x, y));
}




int zonGetNumZoneNord(Zone* p_zone)
{
	assert(p_zone != NULL);
	return p_zone->num_zone_nord;
}

int zonGetNumZoneSud(Zone* p_zone)
{
	assert(p_zone != NULL);
	return p_zone->num_zone_sud;
}

int zonGetNumZoneEst(Zone* p_zone)
{
	assert(p_zone != NULL);
	return p_zone->num_zone_est;
}

int zonGetNumZoneOuest(Zone* p_zone)
{
	assert(p_zone != NULL);
	return p_zone->num_zone_ouest;
}


void zonSetDimension(Zone* p_zone, int dim)
{
    assert(dim>0);

    p_zone->dimension = dim;
}


int zonGetDimension(const Zone* p_zone)
{
    assert(p_zone != NULL);

    return p_zone->dimension;
}





/* vieux, à compléter/modifier...*/
bool zonTestRegression()
{
    Zone z;
    int num_zone = 0; /*pour charger la zone n°0 */


    zonInit(&z, num_zone);


    printf("Bloc (0,0) : %c \n",zonGetBlocXY(&z,0,0));
    printf("Bloc (2,2) : %c \n",zonGetBlocXY(&z,2,2));
    printf("Bloc (29,29) : %c \n",zonGetBlocXY(&z,29,29));

    if (zonEstPositionAccessible(&z,0,0)) {printf("(0,0) est accessible \n");} else{printf("(0,0) n'est pas accessible \n");}
    if (zonEstPositionAccessible(&z,0,7)) {printf("(0,7) est accessible \n");} else{printf("(0,7) n'est pas accessible \n");}


    zonLibere (&z);

	/* tester aussi : zonCree, zonDetruit */


    return true;
}
